#include "World.h"
namespace SLG
{
	World::World(void)
	{
		D3DXCreateTextureFromFile(g_pd3dDevice,"./Res/World/Cell.png",&m_curTex);
		m_cell=NULL;
		m_Figure=NULL;
		m_wWidth=0;
		m_wHeight=0;
		m_curCell=-1;
		m_fManager=NULL;
	}

	World::~World(void)
	{
		delete m_Figure;
		delete m_fManager;
	}

	int32 World::GetCurCellFid()
	{
		return m_cell[m_curCell].fid;
	}

	bool World::AddFigureInCell(int32 idx,int32 x,int32 y)
	{
		if(m_cell[x*m_wWidth+y].fid!=-1)
			return false;
		m_cell[x*m_wWidth+y].fid=idx;
		return true;
	}

	D3DXVECTOR3 World::GetCellPos()
	{
		return m_cell[m_curCell].midPos;
	}

	D3DXVECTOR3 World::GetCellPos(int32 x,int32 y)
	{
		if(!CheckCell(x,y))
			return D3DXVECTOR3(0.0f,0.0f,0.0f);
		return m_cell[x*m_wWidth+y].midPos;
	}

	bool World::CheckCell(int32 x,int32 y)
	{
		if(x<0||y<0||x>=m_wWidth||y>=m_wHeight)
			return false;
		return true;
	}
	
	bool World::InitWorld(Resource* res)
	{
		if(!res->LoadMap(this))
			return false;
		InitCell();
		m_Figure=new FigureObject(this);
		m_fManager=new FightManager(g_pd3dDevice,m_Figure);
		CreateGround();
		UpdateCursorCell(&D3DXVECTOR3(0.0f,0.0f,0.0f));
		if(!res->LoadModel(m_fManager))
			return false;
		if(!m_Figure->LoadAnim())
			return false;
		return true;
	}

	bool World::GetCellIndex(D3DXVECTOR3 pos,int32* x,int32* y)
	{
		for(int i=0;i<m_wHeight;i++)
		{
			for(int j=0;j<m_wWidth;j++)
			{
				if(pos.x>m_cell[i*m_wWidth+j].minPos.x
					&&pos.y>m_cell[i*m_wWidth+j].minPos.y
					&&pos.z>m_cell[i*m_wWidth+j].minPos.z
					&&pos.x<m_cell[i*m_wWidth+j].maxPos.x
					&&pos.y<m_cell[i*m_wWidth+j].maxPos.y
					&&pos.z<m_cell[i*m_wWidth+j].maxPos.z)
				{
					*x=i;
					*y=j;
					return true;
				}
			}
		}
		return false;
	}

	bool World::LoadGround(int32 w, int32 h, const char* fname)
	{
		m_wWidth=w;
		m_wHeight=h;
		m_cell=new Cell[w*h];
		m_sWidth=w*WIDTH_PRE_CELL;
		m_sHeight=h*WIDTH_PRE_CELL;
		if(D3DXCreateTextureFromFile(g_pd3dDevice,fname,&m_tex))
			return false;
		return true;
	}

	void World::InitCell()
	{
		if(m_cell!=NULL)
		{
			delete m_cell;
		}
		m_cell=new Cell[m_wWidth*m_wHeight];
		D3DXVECTOR3 pos=D3DXVECTOR3(WIDTH_PRE_CELL/2,0.0f,WIDTH_PRE_CELL/2);
		D3DXVECTOR3 inc=pos;
		for(int i=0;i<m_wHeight;i++)
		{
			for(int j=0;j<m_wWidth;j++)
			{
				m_cell[i*m_wWidth+j].midPos=pos;
				m_cell[i*m_wWidth+j].minPos=pos-inc;
				m_cell[i*m_wWidth+j].maxPos=pos+inc;
				m_cell[i*m_wWidth+j].fid=-1;
				pos.x+=WIDTH_PRE_CELL;
			}
			pos.x=WIDTH_PRE_CELL/2; 
			pos.z+=WIDTH_PRE_CELL;
		}
	}

	HRESULT World::UpdateCursorCell(D3DXVECTOR3* pos)
	{
		int32 x=pos->x;
		int32 z=pos->z;
		if(x<0||x>=m_wWidth*WIDTH_PRE_CELL
		||z<0||z>=m_wHeight*WIDTH_PRE_CELL)
			return E_FAIL;
		x-=x%(int32)WIDTH_PRE_CELL;
		z-=z%(int32)WIDTH_PRE_CELL;
		pos->x=x,pos->y=0;pos->z=z;
		int32 iw=x/(int32)WIDTH_PRE_CELL;
		int32 ih=z/(int32)WIDTH_PRE_CELL;
		m_curCell=ih*m_wWidth+iw;
		if( FAILED( g_pd3dDevice->CreateVertexBuffer( 4*sizeof( CUSTOMVERTEX ),
			0, D3DFVF_CUSTOMVERTEX,
			D3DPOOL_DEFAULT, &m_curVb, NULL ) ) )
		{
			return E_FAIL;
		}

		CUSTOMVERTEX* pVertices;

		if( FAILED( m_curVb->Lock( 0, 0, ( void** )&pVertices, 0 ) ) )
			return E_FAIL;

		pVertices[0].position=D3DXVECTOR3(pos->x+WIDTH_PRE_CELL,pos->y,pos->z);
		pVertices[0].tu=1.0f;
		pVertices[0].tv=0.0f;

		pVertices[1].position=*pos;
		pVertices[1].tu=0.0f;
		pVertices[1].tv=0.0f;

		pVertices[2].position=D3DXVECTOR3(pos->x+WIDTH_PRE_CELL,pos->y,pos->z+WIDTH_PRE_CELL);
		pVertices[2].tu=1.0f;
		pVertices[2].tv=1.0f;

		pVertices[3].position=D3DXVECTOR3(pos->x,pos->y,pos->z+WIDTH_PRE_CELL);
		pVertices[3].tu=0.0f;
		pVertices[3].tv=1.0f;

		m_curVb->Unlock();

		return S_OK;
	}

	HRESULT World::CreateGround()
	{
		// Buffer to hold vertices
		if( FAILED( g_pd3dDevice->CreateVertexBuffer( 6*m_wWidth*m_wHeight*sizeof( CUSTOMVERTEX ),
			0, D3DFVF_CUSTOMVERTEX,
			D3DPOOL_DEFAULT, &m_vb, NULL ) ) )
		{
			return E_FAIL;
		}

		CUSTOMVERTEX* pVertices;

		if( FAILED( m_vb->Lock( 0, 0, ( void** )&pVertices, 0 ) ) )
			return E_FAIL;

		D3DXVECTOR3 pos=D3DXVECTOR3(0.0f,0.0f,0.0f);
		for(int32 i=0;i<m_wHeight;i++)
		{
			for(int32 j=0;j<m_wWidth;j++)
			{
				pVertices[(i*m_wWidth+j)*6].position=pos;
				pVertices[(i*m_wWidth+j)*6].tu=0.0f;
				pVertices[(i*m_wWidth+j)*6].tv=0.0f;

				pVertices[(i*m_wWidth+j)*6+1].position=D3DXVECTOR3(pos.x+WIDTH_PRE_CELL,pos.y,pos.z);
				pVertices[(i*m_wWidth+j)*6+1].tu=1.0f;
				pVertices[(i*m_wWidth+j)*6+1].tv=0.0f;

				pVertices[(i*m_wWidth+j)*6+2].position=D3DXVECTOR3(pos.x+WIDTH_PRE_CELL,pos.y,pos.z+WIDTH_PRE_CELL);
				pVertices[(i*m_wWidth+j)*6+2].tu=1.0f;
				pVertices[(i*m_wWidth+j)*6+2].tv=1.0f;

				pVertices[(i*m_wWidth+j)*6+3].position=pos;
				pVertices[(i*m_wWidth+j)*6+3].tu=0.0f;
				pVertices[(i*m_wWidth+j)*6+3].tv=0.0f;

				pVertices[(i*m_wWidth+j)*6+4].position=D3DXVECTOR3(pos.x+WIDTH_PRE_CELL,pos.y,pos.z+WIDTH_PRE_CELL);
				pVertices[(i*m_wWidth+j)*6+4].tu=1.0f;
				pVertices[(i*m_wWidth+j)*6+4].tv=1.0f;

				pVertices[(i*m_wWidth+j)*6+5].position=D3DXVECTOR3(pos.x,pos.y,pos.z+WIDTH_PRE_CELL);
				pVertices[(i*m_wWidth+j)*6+5].tu=0.0f;
				pVertices[(i*m_wWidth+j)*6+5].tv=1.0f;
				pos.x+=WIDTH_PRE_CELL;
			}
			pos.z+=WIDTH_PRE_CELL;
			pos.x=0.0f;

		}
		m_vb->Unlock();

		return S_OK;
	}

	void World::DrawGround()
	{
		g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, true);
		D3DXMATRIXA16 matWorld;
		D3DXMatrixIdentity( &matWorld );
		g_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld );

		g_pd3dDevice->SetTexture( 0,m_tex);

		g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE );
		g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
		g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );

		g_pd3dDevice->SetRenderState(D3DRS_ALPHAREF,(DWORD)0x000000A5);
		g_pd3dDevice->SetRenderState(D3DRS_ALPHAFUNC,D3DCMP_GREATEREQUAL);
		g_pd3dDevice->SetStreamSource( 0, m_vb, 0, sizeof( CUSTOMVERTEX ) );
		g_pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX );
		//g_pd3dDevice->SetIndices(m_id);
		//g_pd3dDevice->DrawIndexedPrimitive(   D3DPT_TRIANGLESTRIP    , 0,0,4*m_wWidth*m_wHeight,0,6*m_wWidth*m_wHeight);
		g_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLELIST,0,2*m_wWidth*m_wHeight);



		g_pd3dDevice->SetTexture( 0,m_curTex);
		g_pd3dDevice->SetStreamSource( 0, m_curVb, 0, sizeof( CUSTOMVERTEX ) );
		g_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP,0,2);
		// End the scene
		g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, false);
	}

	void World::Draw(DWORD t)
	{
		DrawGround();
		m_Figure->RenderFigure(t);
	}
}